package com.boat.sample.ddd.infrastructure.persistence.repository;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.gitee.fastmybatis.core.PageInfo;
import com.gitee.fastmybatis.core.query.Query;
import com.boat.framework.base.api.Page;
import com.boat.framework.base.api.PageParam;
import com.boat.framework.common.util.AssertUtils;
import com.boat.framework.common.util.BeanUtils;
import com.boat.framework.common.util.ObjUtils;
import com.boat.framework.common.util.IdUtils;
import com.boat.sample.ddd.domain.system.entity.User;
import com.boat.sample.ddd.domain.system.repository.UserRepository;
import com.boat.sample.ddd.infrastructure.persistence.TableIdCode;
import com.boat.sample.ddd.infrastructure.persistence.factory.UserFactory;
import com.boat.sample.ddd.infrastructure.persistence.mapper.UserMapper;
import com.boat.sample.ddd.infrastructure.persistence.po.UserPo;
import com.boat.sample.ddd.infrastructure.persistence.po.UserColumns;

import lombok.extern.slf4j.Slf4j;

/**
 * User仓储实现类
 * 
 * @author noia_zhou
 *
 */
@Slf4j
@Repository
public class UserRepositoryImpl implements UserRepository {
	@Autowired
	UserFactory userFactory;
	@Autowired
	UserMapper userMapper;

	@Override
	public int insert(User entity) {
	   //非自增ID，通过内置ID生成器ID
       if (ObjUtils.isBlank(entity.getId())) {
			String id = IdUtils.getSequence(TableIdCode.ID_USER);
			entity.setId(id);
		}
		UserPo userPo = userFactory.buildUserPo(entity);
		int count = userMapper.saveIgnoreNull(userPo);
		entity.setId(userPo.getId());
		return count;
	}

	@Override
	public int insertBatch(Collection<User> entitys) {
		List<UserPo> userPos = userFactory.buildUserPoList(entitys);
		return userMapper.saveBatch(userPos);
	}

	@Override
	public int updateById(User entity) {
		AssertUtils.notBlank(entity.getId(), "id不能为空");
        entity.setUpdateTime(new Date());
		UserPo userPo = userFactory.buildUserPo(entity);
		return userMapper.updateIgnoreNull(userPo);
	}

	@Override
	public int deleteById(String id) {
		AssertUtils.notBlank(id, "id不能为空");
        UserPo userPo = userFactory.buildDeleteUserPo(id);
		return userMapper.updateIgnoreNull(userPo);
	}

	@Override
	public int deleteByIds(Collection<String> ids) {
        AssertUtils.notBlank(ids, "ids不能为空");
        
        int count = 0;
		for (String id : ids) {
			count += deleteById(id);
		}
		return count;
	}

	@Override
	public long count(User entity) {
		Query query = buildQuery(entity);
		return userMapper.getCount(query);
	}

	@Override
	public long count(Map<String, Object> map) {
		Query query = buildQuery(map, null);
		return userMapper.getCount(query);
	}

	@Override
	public List<User> listByMap(Map<String, Object> map, PageParam pageParam) {
		AssertUtils.notBlank(map, "map参数不能为空");
		AssertUtils.notBlank(pageParam, "pageParam参数不能为空");
		Query query = buildQuery(map, pageParam);
		List<UserPo> poList = userMapper.list(query);
		return userFactory.buildUserList(poList);
	}

	@Override
	public List<User> listByExample(User entity, PageParam pageParam) {
		AssertUtils.notBlank(entity, "entity参数不能为空");
		AssertUtils.notBlank(pageParam, "pageParam参数不能为空");
		Map<String, Object> map = BeanUtils.beanToMap(entity);
		return listByMap(map, pageParam);
	}

	@Override
	public Page<User> page(User entity, PageParam pageParam) {
		AssertUtils.notBlank(pageParam, "分页参数不能为空");
		Map<String, Object> map = BeanUtils.beanToMap(entity);
		return page(map, pageParam);
	}

	@Override
	public Page<User> page(Map<String, Object> map, PageParam pageParam) {
		AssertUtils.notBlank(pageParam, "分页参数不能为空");
		Query query = buildQuery(map, pageParam);
		PageInfo<UserPo> pageInfo = userMapper.page(query);
		List<User> userList = userFactory.buildUserList(pageInfo.getList());
		return Page.<User>builder().total(pageInfo.getTotal()).list(userList).build();
	}

	@Override
	public User getById(String id) {
		UserPo userPo = userMapper.getById(id);
		return userFactory.buildUser(userPo);
	}

	@Override
	public User getByMap(Map<String, Object> map) {
		AssertUtils.notBlank(map, "参数不能为空");
		Query query = buildQuery(map, null);
		UserPo userPo = userMapper.getByQuery(query);
		return userFactory.buildUser(userPo);
	}

	@Override
	public User getByExample(User entity) {
		AssertUtils.notBlank(entity, "参数不能为空");
		Query query = buildQuery(entity);
		UserPo userPo = userMapper.getByQuery(query);
		return userFactory.buildUser(userPo);
	}

	// 组装查询条件
	private Query buildQuery(User entity) {
		Map<String, Object> map = BeanUtils.beanToMap(entity);
		return buildQuery(map, null);
	}

	private Query buildQuery(Map<String, Object> paramMap, PageParam pageParam) {
		Query query = new Query();
        // 精确查询
		query.eq(ObjUtils.notBlank(paramMap.get("id")), UserColumns.ID, paramMap.get("id"));
		query.eq(ObjUtils.notBlank(paramMap.get("userName")), UserColumns.USER_NAME, paramMap.get("userName"));
		query.eq(ObjUtils.notBlank(paramMap.get("nickName")), UserColumns.NICK_NAME, paramMap.get("nickName"));
		query.eq(ObjUtils.notBlank(paramMap.get("password")), UserColumns.PASSWORD, paramMap.get("password"));
		query.eq(ObjUtils.notBlank(paramMap.get("userType")), UserColumns.USER_TYPE, paramMap.get("userType"));
		query.eq(ObjUtils.notBlank(paramMap.get("email")), UserColumns.EMAIL, paramMap.get("email"));
		query.eq(ObjUtils.notBlank(paramMap.get("phone")), UserColumns.PHONE, paramMap.get("phone"));
		query.eq(ObjUtils.notBlank(paramMap.get("status")), UserColumns.STATUS, paramMap.get("status"));
		query.eq(ObjUtils.notBlank(paramMap.get("createTime")), UserColumns.CREATE_TIME, paramMap.get("createTime"));
		query.eq(ObjUtils.notBlank(paramMap.get("updateTime")), UserColumns.UPDATE_TIME, paramMap.get("updateTime"));
		query.eq(ObjUtils.notBlank(paramMap.get("createBy")), UserColumns.CREATE_BY, paramMap.get("createBy"));
		query.eq(ObjUtils.notBlank(paramMap.get("updateBy")), UserColumns.UPDATE_BY, paramMap.get("updateBy"));
		query.eq(ObjUtils.notBlank(paramMap.get("remark")), UserColumns.REMARK, paramMap.get("remark"));
		query.eq(ObjUtils.notBlank(paramMap.get("deleted")), UserColumns.DELETED, paramMap.get("deleted"));
        // 默认只查询未删除数据
		query.eq(ObjUtils.isBlank(paramMap.get("deleted")), UserColumns.DELETED, 0);
		// 时间范围查询
		query.ge(ObjUtils.notBlank(paramMap.get("createTimeStart")), UserColumns.CREATE_TIME, paramMap.get("createTimeStart"));
		query.le(ObjUtils.notBlank(paramMap.get("createTimeEnd")), UserColumns.CREATE_TIME, paramMap.get("createTimeEnd"));
		query.ge(ObjUtils.notBlank(paramMap.get("updateTimeStart")), UserColumns.UPDATE_TIME, paramMap.get("updateTimeStart"));
		query.le(ObjUtils.notBlank(paramMap.get("updateTimeEnd")), UserColumns.UPDATE_TIME, paramMap.get("updateTimeEnd"));
		// in查询
		query.in(ObjUtils.notBlank(paramMap.get("idIn")), UserColumns.ID, (Collection<?>)paramMap.get("idIn"));

		/*
		 * Query支持模糊查询，时间范围查询、in、子查询、or子句等，可查看Query API文档。
		 * 详细示例参考：https://durcframework.gitee.io/fastmybatis/#/files/10012_%E6%9F%A5%E8%AF%A2?t=1652961702856&id=query%e7%b1%bb%e8%af%a6%e8%a7%a3
		 */
		
		if (pageParam == null) {
			// 没有设置条件，限制返回记录数，避免加载所有数据
			query.limit(0, PageParam.MAX_PAGE_SIZE);
		} else {
			query.page(pageParam.getPageNum(), pageParam.getPageSize());
			pageParam.getOrders().forEach(order -> query.addSort(order.getTableColumn(), order.getSort()));
		}
		return query;
	}
}